package com.mall.order.config;

import com.mall.common.constant.OrderConstant;
import com.mall.order.rabbit.RabbitMessageEntity;
import com.mall.order.rabbit.RabbitMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: 谢君臣
 * @Date: 2022/8/9-16:12
 * @version: 1.0
 * @function:
 */
@Slf4j
@Configuration
public class RabbitMqConfig {

    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private RabbitMessageService rabbitMessageService;


    @PostConstruct
    public void initRabbitTemplate(){
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                // 提交数据库
                // todo 可靠消息
                System.out.println("消息编号:"+correlationData.getId()+",消息投递到阻塞队列 Broker 状态:" + b);
                String msgId = correlationData.getId();
                ReturnedMessage returnedMessage = correlationData.getReturned();
                if (returnedMessage != null){
                    String message = new String(returnedMessage.getMessage().getBody());
                    String exchange = returnedMessage.getExchange();
                    String routingKey = returnedMessage.getRoutingKey();
                    String replyText = returnedMessage.getReplyText();
                    RabbitMessageEntity rabbitMessageDto = new RabbitMessageEntity(null,msgId,message,exchange,routingKey,replyText,1L,new Date(),null);
                    boolean insert = rabbitMessageService.insert(rabbitMessageDto);
                    if (!insert) log.error("消息落库失败！");
                }
            }
        });
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                // 消息失败 更改数据库状态
                // todo 可靠消息

            }
        });
    }


    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public Queue orderDelayQueue(){
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange","order-event-exchange");
        arguments.put("x-dead-letter-routing-key","order.release.other");
        // 10 分钟自动关单
        arguments.put("x-message-ttl", OrderConstant.ORDER_RABBITMQ_TIMEOUT_LENGTH);
        return new Queue("order.delay.queue", true, false, false,arguments);
    }
    @Bean
    public Queue orderReleaseOrderQueue(){
        return new Queue("order.release.queue", true, false, false);
    }
    @Bean
    public Queue orderSuccessOrderQueue(){
        return new Queue("order.success.queue", true, false, false);
    }
    @Bean
    public Exchange orderEventExchange(){
        return new TopicExchange("order-event-exchange",true,false);
    }
    @Bean
    public Binding createBinding_orderCreate() {
        return new Binding(
                "order.delay.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.create",
                null
        );
    }
    @Bean
    public Binding createBinding_orderRelease() {
        return new Binding(
                "order.release.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.release.#",
                null
        );
    }
    @Bean
    public Binding createBinding_orderSuccess() {
        return new Binding(
                "order.success.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.success.#",
                null
        );
    }

}
